package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;

    private final OrderDetailMapper orderDetailMapper;

    private final ShoppingCartMapper shoppingCartMapper;

    private final AddressBookMapper addressBookMapper;

    private final WeChatPayUtil weChatPayUtil;

    private final UserMapper userMapper;

    private final WebSocketServer webSocketServer;

    /**
     * 用户下单
     *
     * @param ordersSubmitDTO
     * @return
     */
    @Transactional //因为设计到了多表的操作 所有需要加上事务注解保证数据的一致性
    @Override
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
        //1.异常情况的处理（收货地址为空、超出配送范围、购物车为空）
        //根据地址簿id 查询用户地址数据
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            //说明没有地址信息抛出业务异常
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        //查询当前用户的购物车数据
        Long userId = BaseContext.getCurrentId();//获取用户id
        ShoppingCart shoppingCart = ShoppingCart.builder()
                .userId(userId) //构建shoppingCart对象封装查询条件
                .build();
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);
        if (shoppingCartList == null || shoppingCartList.size() == 0) {
            //说明购物车数据为空 不能下单抛出异常
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }

        //2.向订单表插入一条数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        //补全属性
        orders.setOrderTime(LocalDateTime.now());//设置下单时间
        orders.setPayStatus(Orders.UN_PAID); //设置支付状态 Orders.UN_PAID表示未支付
        orders.setStatus(Orders.PENDING_PAYMENT);//设置订单状态 Orders.PENDING_PAYMENT表示待付款
        orders.setNumber(String.valueOf(System.currentTimeMillis()));//设置订单号 使用当前系统的时间戳作为订单号
        orders.setPhone(addressBook.getPhone());//设置手机好
        orders.setConsignee(addressBook.getConsignee());//设置收货人
        orders.setUserId(userId);//设置用户id
        orders.setAddress(addressBook.getDetail());//设置地址
        orders.setOrderTime(LocalDateTime.now());//设置下单时间

        orderMapper.insert(orders);

        List<OrderDetail> orderDetailList = new ArrayList<>();
        //3.向订单明细表插入n条数据
        shoppingCartList.forEach(cart -> { //遍历购物车
            //每遍历一次购物车封装成一个订单明细对象
            OrderDetail orderDetail = new OrderDetail();//订单明显对象
            BeanUtils.copyProperties(cart, orderDetail);//属性拷贝把购物车对象的属性拷贝的订单明显表中
            //因为购物车中没有orderId(订单id)所有需要单独设置
            //设置当前订单关联的订单id
            orderDetail.setOrderId(orders.getId()); //这里通过orders.getId()在mapper映射文件中一定要设置主键返回否则会获取不到
            orderDetailList.add(orderDetail); //把数据都存放到集合中
        });

        //使用批量插入性能更好
        orderDetailMapper.insertBatch(orderDetailList);

        //4.清空当前用户的购物车数据
        shoppingCartMapper.deleteByUserId(userId);

        //5.封装VO对象返回
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId()) //设置订单id
                .orderTime(orders.getOrderTime()) //设置下单时间
                .orderNumber(orders.getNumber()) //设置订单号
                .orderAmount(orders.getAmount()) //设置总金额
                .build();

        return orderSubmitVO;
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        //User user = userMapper.getById(userId);

        //调用微信支付接口，生成预支付交易单
//        JSONObject jsonObject = weChatPayUtil.pay(
//                ordersPaymentDTO.getOrderNumber(), //商户订单号
//                new BigDecimal(0.01), //支付金额，单位 元
//                "苍穹外卖订单", //商品描述
//                user.getOpenid() //微信用户的openid
//        );
//
//        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
//            throw new OrderBusinessException("该订单已支付");
//        }

        // 跳过微信支付，直接支付成功
        OrderPaymentVO orderPaymentVO = new OrderPaymentVO();
        orderPaymentVO.setNonceStr("1");
        orderPaymentVO.setPackageStr("prepay_id=:prepay_id");
        orderPaymentVO.setTimeStamp("1");
        orderPaymentVO.setSignType("MD5");
        orderPaymentVO.setPaySign("1");

        //在修改订单支付状态
        paySuccess(ordersPaymentDTO.getOrderNumber());//调用paySuccess方法修改订单支付状态
        return orderPaymentVO;


/*        // 创建一个JSONObject，用于存储订单支付相关的数据
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "ORDERPAID");

        // 将JSON对象转换为OrderPaymentVO对象，以便进一步处理订单支付信息
        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        // 从JSON对象中获取并设置订单的package信息
        vo.setPackageStr(jsonObject.getString("package"));

        // 定义订单支付状态和订单状态常量
        // 为替代微信支付成功后的数据库订单状态更新，多定义一个方法进行修改
        Integer orderPayStatus = Orders.PAID; //支付状态，已支付
        Integer orderStatus = Orders.TO_BE_CONFIRMED;  //订单状态，待接单

        // 将订单号字符串转换为长整型，以便进行数据库操作
        Long orderId = Long.valueOf(ordersPaymentDTO.getOrderNumber());

        // 记录当前时间作为订单支付时间
        // 发现没有将支付时间 check_out属性赋值，所以在这里更新
        LocalDateTime time = LocalDateTime.now();

        // 调用orderMapper的updateStatus方法，更新订单状态和支付状态
        orderMapper.updateStatus(orderPayStatus, orderStatus, time, orderId, userId);
        //orderMapper.updateStatus(OrderStatus, OrderPaidStatus, check_out_time, orderid, userId);
        return vo;*/
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo 订单号
     */
    public void paySuccess(String outTradeNo) {

        // 根据订单号查询订单
        Orders ordersDB = orderMapper.getByNumber(outTradeNo);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        orderMapper.update(orders);

        //通过websocket向客户端浏览器推送信息 type orderId content
        Map map = new HashMap();
        map.put("type", 1); //1表示来单提醒 2表示客户催单
        map.put("orderId", ordersDB.getId());
        map.put("content", "订单号" + outTradeNo);

        //把map转成json字符串
        String json = JSON.toJSONString(map);
        //向页面推送信息
        webSocketServer.sendToAllClient(json);
    }

    /**
     * 分页查询历史订单
     *
     * @param ordersPageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(OrdersPageQueryDTO ordersPageQueryDTO) {
        //调用PageHelper的静态方法 传递两个参数分别就是页码和每页展示记录数
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());//设置分页查询
        //通过ThreadLocal获取用户id
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());//设置用户id

        //执行分页查询
        Page<Orders> p = orderMapper.pageQuery(ordersPageQueryDTO);

        //新建一个用于存放OrderVO的集合
        List<OrderVO> list = new ArrayList<>();
        //判断分页查询的结果是否为空 是否有数据
        if (p != null && p.getTotal() > 0) {
            //说明有数据 遍历分页查询的结果
            p.forEach(orders -> {
                //获取订单id
                Long orderId = orders.getId();
                //根据订单id查询订单明细
                List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orderId);

                //构建OrderVO对象
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders, orderVO);//将属性拷贝到vo对象中
                //补充属性
                orderVO.setOrderDetailList(orderDetailList);
                //将vo对象添加到list集合
                list.add(orderVO);
            });
        }
        //注意这里返回的是list集合是orderVO对象
        return new PageResult(p.getTotal(), list);
    }

    /**
     * 查询订单详情
     *
     * @param id 订单id
     * @return
     */
    @Override
    public OrderVO details(Long id) {
        //根据id查询订单
        Orders orders = orderMapper.getById(id);//获取订单对象

        //根据订单id查询订单细节信息
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());

        // 将该订单及其详情封装到OrderVO并返回
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders, orderVO);
        orderVO.setOrderDetailList(orderDetailList);//单独设置订单细节信息

        return orderVO;
    }

    /**
     * 用户取消订单
     *
     * @param id 订单id
     */
    @Override
    public void userCancelById(Long id) {
        /*
         业务规则
        -待支付和待接单状态下，用户可直接取消订单 /
        - 商家已接单状态下，用户取消订单需电话沟通商家
        - 派送中状态下，用户取消订单需电话沟通商家
        - 如果在待接单状态下取消订单，需要给用户退款
        - 取消订单后需要将订单状态修改为“已取消”
         */
        //根据订单id获取订单对象
        Orders orders = orderMapper.getById(id);
        //校验订单是否存在
        if (orders == null) {
            //说明没有订单信息抛出业务异常
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //获取订单的状态
        if (orders.getStatus() > 2) {
            //如果订单的状态大于二 那么不能直接取消订单
            //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消 7退款
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        // 订单处于待接单状态下取消，需要进行退款
        if (orders.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
            //由于没有实现微信支付 所有用户取消订单默认就是已经退款
            //调用微信支付接口退款
/*            weChatPayUtil.refund(
                    orders.getNumber(), //商户订单号
                    orders.getNumber(), //商户退款单号
                    new BigDecimal(0.01),//退款金额，单位 元
                    new BigDecimal(0.01));//原订单金额*/

            //支付状态修改为 退款
            orders.setPayStatus(Orders.REFUND);
        }

        // 更新订单状态、取消原因、取消时间
        orders.setStatus(Orders.CANCELLED); //Orders.CANCELLED表示取消
        orders.setCancelReason("用户取消");
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 再来一单
     *
     * @param id 订单id
     */
    @Override
    public void repetition(Long id) {
        //再来一单就是将当前商品再添加到购物车中
        //获取当前用户id
        Long userId = BaseContext.getCurrentId();

        //根据订单ID查询订单详情列表，这一步是为了获取用户订单中的所有商品详情，以便后续将这些详情转换为购物车项。
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);

        // 第一种 使用stream流
        // 将订单详情转换为购物车项对象。这里使用了流式处理来遍历订单详情列表，对每个订单详情创建一个对应的购物车项，并设置相应的属性，包括用户ID和创建时间。
        List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(orderDetail -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            // 复制订单详情的属性到购物车项中，但不包括ID，因为购物车项应该有一个新的独立ID。
            // 因为订单详情的数据，本质其实放的就是购物车的数据 所有将订单详情的数据，转成购物车数据
            BeanUtils.copyProperties(orderDetail, shoppingCart, "id");
            shoppingCart.setUserId(userId); //设置用户id
            shoppingCart.setCreateTime(LocalDateTime.now()); //设置创建时间

            return shoppingCart;
            //collect(Collector collector) 把stream流处理好的数据收集到集合中。收集到list集合中就调用toList 收集到map中调用toMap
        }).collect(Collectors.toList());

        // 将购物车对象批量添加到数据库
        shoppingCartMapper.insertBatch(shoppingCartList);


        /*
        // 第二种循环遍历
        // 初始化一个购物车列表，用于存储即将插入数据库的购物车信息
        List<ShoppingCart> shoppingCartList = new ArrayList<>();

        // 遍历订单详情列表，为每个订单详情创建对应的购物车对象，并填充相关信息
        orderDetailList.forEach(orderDetail -> {
            // 创建一个新的购物车对象
            ShoppingCart shoppingCart = new ShoppingCart();
            // 将订单详情的信息复制到购物车对象中，排除id属性
            BeanUtils.copyProperties(orderDetail, shoppingCart, "id");
            // 设置购物车的用户ID，这里假设userId已经在此之前被正确赋值
            shoppingCart.setUserId(userId);
            // 设置购物车的创建时间为当前时间
            shoppingCart.setCreateTime(LocalDateTime.now());
            // 将购物车对象添加到购物车列表中
            shoppingCartList.add(shoppingCart);
        });

        // 批量插入购物车列表中的所有购物车对象到数据库
        shoppingCartMapper.insertBatch(shoppingCartList);
        */
    }

    /**
     * 条件搜索订单 - 管理端
     *
     * @param ordersPageQueryDTO 包含分页信息和查询条件的订单页面查询DTO。
     * @return 返回包含订单信息的分页结果。
     */
    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        // 初始化分页插件
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        // 执行订单查询
        Page<Orders> page = orderMapper.pageQuery(ordersPageQueryDTO);

        // 将查询结果转换为OrderVO列表
        // 部分订单状态，需要额外返回订单菜品信息，将Orders转化为OrderVO
        List<OrderVO> orderVOList = getOrderVOList(page);

        // 构建并返回分页结果
        return new PageResult(page.getTotal(), orderVOList);
    }

    /**
     * 将订单分页结果转换为OrderVO列表。
     *
     * @param page 订单的分页结果。
     * @return 返回转换后的OrderVO列表。
     */
    private List<OrderVO> getOrderVOList(Page<Orders> page) {
        // 初始化OrderVO列表
        // 需要返回订单菜品信息，自定义OrderVO响应结果
        List<OrderVO> orderVOList = new ArrayList<>();

        // 获取分页结果中的订单列表
        List<Orders> ordersList = page.getResult();
        // 避免空指针异常
        if (!CollectionUtils.isEmpty(ordersList)) {
            // 遍历订单列表
            for (Orders orders : ordersList) {
                // 创建一个新的OrderVO对象，并复制Orders的数据到其中
                // 将共同字段复制到OrderVO
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders, orderVO);
                // 获取并设置订单的菜品信息字符串
                String orderDishes = getOrderDishesStr(orders);
                orderVO.setOrderDishes(orderDishes);
                // 将OrderVO添加到列表中
                orderVOList.add(orderVO);
            }
        }
        return orderVOList;
    }

    /**
     * 根据订单ID获取订单的菜品信息字符串。
     *
     * @param orders 订单对象。
     * @return 返回订单的菜品信息字符串。
     */
    private String getOrderDishesStr(Orders orders) {
        // 根据订单ID查询订单详情列表
        // 查询订单菜品详情信息（订单中的菜品和数量）
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());

        // 将订单详情转换为菜品信息字符串列表
        // 将每一条订单菜品信息拼接为字符串（格式：宫保鸡丁*3；）
        List<String> orderDishList = orderDetailList.stream().map(x -> {
            String orderDish = x.getName() + "*" + x.getNumber() + ";";
            return orderDish;
        }).collect(Collectors.toList());

        // 将菜品信息字符串列表合并为一个字符串
        // 将该订单对应的所有菜品信息拼接在一起
        return String.join("", orderDishList);
    }

    /**
     * 各个状态的订单数量统计 - 管理端
     *
     * @return
     */
    @Override
    public OrderStatisticsVO statistics() {
        // 根据状态，分别查询出待接单、待派送、派送中的订单数量
        // 订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        Integer toBeConfirmed = orderMapper.countStatus(Orders.TO_BE_CONFIRMED); //表示待接单
        Integer confirmed = orderMapper.countStatus(Orders.CONFIRMED); //表示已接单
        Integer deliveryInProgress = orderMapper.countStatus(Orders.DELIVERY_IN_PROGRESS); //表示派送中

        // 分装VO对象返回
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);

        return orderStatisticsVO;
    }

    /**
     * 接单 - 管理端
     *
     * @param ordersConfirmDTO
     */
    @Override
    public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        //商家接单 本质就是将订单的状态修改为已接单
        //获取订单对象
//        Orders orders = orderMapper.getById(ordersConfirmDTO.getId());
//        BeanUtils.copyProperties(ordersConfirmDTO, orders);
//        orders.setStatus(Orders.CONFIRMED);

        //构建订单对象 设置修改条件
        Orders orders = Orders.builder()
                .id(ordersConfirmDTO.getId())
                .status(Orders.CONFIRMED) //表示已接单
                .build();
        orderMapper.update(orders);
    }

    /**
     * 拒单 - 管理端
     *
     * @param ordersRejectionDTO
     */
    @Override
    public void rejection(OrdersRejectionDTO ordersRejectionDTO) {
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        //商家拒单 本质就是将订单的状态修改为已取消
        //获取订单对象
        Orders orders = orderMapper.getById(ordersRejectionDTO.getId());
        //只有订单存在并且 订单的状态为2才可以拒单
        if (orders == null) {
            //说明没有订单信息抛出业务异常
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        if (orders.getStatus() != 2) {
            //说明订单不是待接单状态不能拒单
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        //获取支付状态
        Integer payStatus = orders.getStatus();
        if (payStatus == Orders.PAID) { // Orders.PAID表示已支付
            //说明用户已支付 需要退款
            //由于跳过微信支付所以直接设置状态即可
/*            String refund = weChatPayUtil.refund(
                    ordersDB.getNumber(),
                    ordersDB.getNumber(),
                    new BigDecimal(0.01),
                    new BigDecimal(0.01));
            log.info("申请退款：{}", refund);*/
        }

        // 拒单需要退款，根据订单id更新订单状态、拒单原因、取消时间
        //构建订单对象 设置修改条件
        Orders orders1 = new Orders();
        orders1.setId(orders.getId()); //设置订单id
        orders1.setStatus(Orders.CANCELLED); //设置订单状态为 已取消
        orders1.setRejectionReason(ordersRejectionDTO.getRejectionReason()); //设置取消原因
        orders1.setCancelTime(LocalDateTime.now()); //设置取消时间
        orderMapper.update(orders1);
    }

    /**
     * 取消订单 - 管理端
     *
     * @param ordersCancelDTO
     */
    @Override
    public void cancel(OrdersCancelDTO ordersCancelDTO) {
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        //商家拒单 本质就是将订单的状态修改为已取消
        //获取订单对象
        Orders orders = orderMapper.getById(ordersCancelDTO.getId());

        //获取支付状态
        Integer status = orders.getStatus();
        if (status == Orders.PAID) {
            //说明用户已支付 需要退款
            //由于跳过微信支付所以直接设置状态即可
/*            String refund = weChatPayUtil.refund(
                    ordersDB.getNumber(),
                    ordersDB.getNumber(),
                    new BigDecimal(0.01),
                    new BigDecimal(0.01));
            log.info("申请退款：{}", refund);*/
        }

        // 取消订单需要退款，根据订单id更新订单状态、拒单原因、取消时间
        Orders orders1 = new Orders();
        orders1.setId(ordersCancelDTO.getId());//设置订单id
        orders1.setStatus(Orders.CANCELLED);//设置订单状态为 已取消
        orders1.setCancelReason(ordersCancelDTO.getCancelReason());//设置取消原因
        orders1.setCancelTime(LocalDateTime.now());//设置取消时间

/*        orders.setId(ordersCancelDTO.getId());
        orders.setRejectionReason(ordersCancelDTO.getCancelReason());
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelTime(LocalDateTime.now()); */
        orderMapper.update(orders1);
    }

    /**
     * 派送订单 - 管理端
     *
     * @param id 订单id
     */
    @Override
    public void delivery(Long id) {
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        //派送订单 本质就是将订单的状态修改为派送中
        //获取订单对象
        Orders orders = orderMapper.getById(id);

        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //校验订单是否为已接单状态
        if (!orders.getStatus().equals(Orders.CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        Orders orders1 = new Orders();
        orders1.setId(orders.getId());//设置订单id 如果忘记了会修改到其他的订单
        //设置订单状态为派送中
        orders1.setStatus(Orders.DELIVERY_IN_PROGRESS);
        //修改订单状态
        orderMapper.update(orders1);
    }

    /**
     * 完成订单 - 管理端
     *
     * @param id
     */
    @Override
    public void complete(Long id) {
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        //完成订单 本质就是将订单的状态修改为已完成
        //获取订单对象
        Orders orders = orderMapper.getById(id);
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //校验订单是否为派送中状态
        if (!orders.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        Orders orders1 = new Orders();
        orders1.setId(orders.getId());//设置订单id 如果忘记了会修改到其他的订单
        //设置订单状态为已完成
        orders1.setStatus(Orders.COMPLETED);
        //修改订单状态
        orderMapper.update(orders1);
    }

    /**
     * 客户催单 - 客户端
     *
     * @param id 订单id
     */
    @Override
    public void reminder(Long id) {
        //获取订单id获取订单对象
        Orders orders = orderMapper.getById(id);
        //校验订单是否存在
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //通过websocket向客户端浏览器推送信息 type orderId content
        Map map = new HashMap();
        map.put("type", 2); //1表示来单提醒 2表示客户催单
        map.put("orderId", id);
        map.put("content", "订单号" + orders.getNumber());

        //把map转成json字符串
        String json = JSON.toJSONString(map);
        //通过websocket向页面推送信息
        webSocketServer.sendToAllClient(json);
    }
}
